From: Jonas Dreßler Date: Sat, 6 Aug 2022 12:46:50 +0000 (+0200) Subject: st/scroll-bar: Port scroll bar scrolling to use ClutterGesture X-Git-Tag: archive/raspbian/50.5-1+rpi1~1^2~104^2^2~31 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=4541663470954a62b2071fd8a93d904ff9b0eb9c;p=gnome-shell.git st/scroll-bar: Port scroll bar scrolling to use ClutterGesture Avoid the troublesome event handling here and replace it with two ClutterPanGestures, one for the trough and one for the handle. This is a fairly non-intrusive port, there's room for a lot of improvements, for example making the trough react to motion events too should be fairly easy now. Part-of: --- diff --git a/src/st/st-scroll-bar.c b/src/st/st-scroll-bar.c index 32dbcd7e3..056f9870c 100644 --- a/src/st/st-scroll-bar.c +++ b/src/st/st-scroll-bar.c @@ -52,15 +52,15 @@ struct _StScrollBarPrivate gfloat x_origin; gfloat y_origin; - ClutterInputDevice *grab_device; - ClutterGrab *grab; - ClutterActor *trough; ClutterActor *handle; gfloat move_x; gfloat move_y; + ClutterPanGesture *trough_pan_gesture; + ClutterPanGesture *handle_pan_gesture; + /* Trough-click handling. */ enum { NONE, UP, DOWN } paging_direction; guint paging_source_id; @@ -95,13 +95,6 @@ enum static guint signals[LAST_SIGNAL] = { 0, }; -static gboolean -handle_button_press_event_cb (ClutterActor *actor, - ClutterEvent *event, - StScrollBar *bar); - -static void stop_scrolling (StScrollBar *bar); - ClutterOrientation st_scroll_bar_get_orientation (StScrollBar *bar) { @@ -212,9 +205,12 @@ st_scroll_bar_dispose (GObject *gobject) static void st_scroll_bar_unmap (ClutterActor *actor) { - CLUTTER_ACTOR_CLASS (st_scroll_bar_parent_class)->unmap (actor); + StScrollBarPrivate *priv = st_scroll_bar_get_instance_private (ST_SCROLL_BAR (actor)); + + if (priv->handle) + clutter_gesture_cancel (CLUTTER_GESTURE (priv->handle_pan_gesture)); - stop_scrolling (ST_SCROLL_BAR (actor)); + CLUTTER_ACTOR_CLASS (st_scroll_bar_parent_class)->unmap (actor); } static void @@ -647,91 +643,6 @@ move_slider (StScrollBar *bar, st_adjustment_set_value (priv->adjustment, position); } -static void -stop_scrolling (StScrollBar *bar) -{ - StScrollBarPrivate *priv = st_scroll_bar_get_instance_private (bar); - if (!priv->grab_device) - return; - - st_widget_remove_style_pseudo_class (ST_WIDGET (priv->handle), "active"); - - if (priv->grab) - { - clutter_grab_dismiss (priv->grab); - g_clear_object (&priv->grab); - } - - priv->grab_device = NULL; - g_signal_emit (bar, signals[SCROLL_STOP], 0); -} - -static gboolean -handle_motion_event_cb (ClutterActor *trough, - ClutterEvent *event, - StScrollBar *bar) -{ - StScrollBarPrivate *priv = st_scroll_bar_get_instance_private (bar); - graphene_point_t coords; - - if (!priv->grab_device) - return FALSE; - - clutter_event_get_position (event, &coords); - move_slider (bar, coords.x, coords.y); - return TRUE; -} - -static gboolean -handle_button_release_event_cb (ClutterActor *trough, - ClutterEvent *event, - StScrollBar *bar) -{ - if (clutter_event_get_button (event) != 1) - return FALSE; - - stop_scrolling (bar); - return TRUE; -} - -static gboolean -handle_button_press_event_cb (ClutterActor *actor, - ClutterEvent *event, - StScrollBar *bar) -{ - StScrollBarPrivate *priv = st_scroll_bar_get_instance_private (bar); - ClutterInputDevice *device = clutter_event_get_device (event); - graphene_point_t coords; - ClutterActor *stage; - - if (clutter_event_get_button (event) != 1) - return FALSE; - - clutter_event_get_position (event, &coords); - - if (!clutter_actor_transform_stage_point (priv->handle, - coords.x, - coords.y, - &priv->x_origin, - &priv->y_origin)) - return FALSE; - - st_widget_add_style_pseudo_class (ST_WIDGET (priv->handle), "active"); - - /* Account for the scrollbar-trough-handle nesting. */ - priv->x_origin += clutter_actor_get_x (priv->trough); - priv->y_origin += clutter_actor_get_y (priv->trough); - - g_assert (!priv->grab_device); - - stage = clutter_actor_get_stage (actor); - priv->grab = clutter_stage_grab (CLUTTER_STAGE (stage), priv->handle); - priv->grab_device = device; - g_signal_emit (bar, signals[SCROLL_START], 0); - - return TRUE; -} - static gboolean trough_paging_cb (StScrollBar *self) { @@ -855,63 +766,94 @@ trough_paging_cb (StScrollBar *self) return ret; } -static gboolean -trough_button_press_event_cb (ClutterActor *actor, - ClutterEvent *event, - StScrollBar *self) +static void +trough_pan_recognize_cb (ClutterPanGesture *pan_gesture, + StScrollBar *self) { - StScrollBarPrivate *priv; - graphene_point_t coords; - - g_return_val_if_fail (self, FALSE); - - if (clutter_event_get_button (event) != 1) - return FALSE; + StScrollBarPrivate *priv = st_scroll_bar_get_instance_private (self); + graphene_point_t centroid; - priv = st_scroll_bar_get_instance_private (self); - if (priv->adjustment == NULL) - return FALSE; + if (!priv->adjustment) + return; - clutter_event_get_position (event, &coords); + clutter_pan_gesture_get_centroid_abs (pan_gesture, ¢roid); - priv->move_x = coords.x; - priv->move_y = coords.y; + priv->move_x = centroid.x; + priv->move_y = centroid.y; priv->paging_direction = NONE; priv->paging_event_no = 0; trough_paging_cb (self); - - return TRUE; } -static gboolean -trough_button_release_event_cb (ClutterActor *actor, - ClutterEvent *event, - StScrollBar *self) +static void +trough_pan_end_cb (ClutterPanGesture *pan_gesture, + StScrollBar *self) { StScrollBarPrivate *priv = st_scroll_bar_get_instance_private (self); - if (clutter_event_get_button (event) != 1) - return FALSE; + g_clear_handle_id (&priv->paging_source_id, g_source_remove); +} + +static void +trough_pan_cancel_cb (ClutterPanGesture *pan_gesture, + StScrollBar *self) +{ + StScrollBarPrivate *priv = st_scroll_bar_get_instance_private (self); g_clear_handle_id (&priv->paging_source_id, g_source_remove); +} - return TRUE; +static void +handle_pan_recognize_cb (ClutterPanGesture *pan_gesture, + StScrollBar *self) +{ + StScrollBarPrivate *priv = st_scroll_bar_get_instance_private (self); + graphene_point_t centroid; + + clutter_pan_gesture_get_centroid_abs (pan_gesture, ¢roid); + if (!clutter_actor_transform_stage_point (priv->handle, centroid.x, centroid.y, ¢roid.x, ¢roid.y)) + return; + + priv->x_origin = centroid.x; + priv->y_origin = centroid.y; + + st_widget_add_style_pseudo_class (ST_WIDGET (priv->handle), "active"); + + /* Account for the scrollbar-trough-handle nesting. */ + priv->x_origin += clutter_actor_get_x (priv->trough); + priv->y_origin += clutter_actor_get_y (priv->trough); + + g_signal_emit (self, signals[SCROLL_START], 0); } -static gboolean -trough_leave_event_cb (ClutterActor *actor, - ClutterEvent *event, - StScrollBar *self) +static void +handle_pan_update_cb (ClutterPanGesture *pan_gesture, + StScrollBar *self) +{ + graphene_point_t centroid; + + clutter_pan_gesture_get_centroid_abs (pan_gesture, ¢roid); + move_slider (self, centroid.x, centroid.y); +} + +static void +handle_pan_end_cb (ClutterPanGesture *pan_gesture, + StScrollBar *self) { StScrollBarPrivate *priv = st_scroll_bar_get_instance_private (self); - if (priv->paging_source_id) - { - g_clear_handle_id (&priv->paging_source_id, g_source_remove); - return TRUE; - } + st_widget_remove_style_pseudo_class (ST_WIDGET (priv->handle), "active"); + g_signal_emit (self, signals[SCROLL_STOP], 0); +} - return FALSE; +static void +handle_pan_cancel_cb (ClutterPanGesture *pan_gesture, + StScrollBar *self) +{ + StScrollBarPrivate *priv = st_scroll_bar_get_instance_private (self); + + st_widget_remove_style_pseudo_class (ST_WIDGET (priv->handle), "active"); + g_signal_emit (self, signals[SCROLL_STOP], 0); } static void @@ -935,12 +877,20 @@ st_scroll_bar_init (StScrollBar *self) clutter_actor_set_name (CLUTTER_ACTOR (priv->trough), "trough"); clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->trough)); - g_signal_connect (priv->trough, "button-press-event", - G_CALLBACK (trough_button_press_event_cb), self); - g_signal_connect (priv->trough, "button-release-event", - G_CALLBACK (trough_button_release_event_cb), self); - g_signal_connect (priv->trough, "leave-event", - G_CALLBACK (trough_leave_event_cb), self); + + priv->trough_pan_gesture = CLUTTER_PAN_GESTURE (clutter_pan_gesture_new ()); + clutter_pan_gesture_set_begin_threshold (priv->trough_pan_gesture, 0); + clutter_actor_meta_set_name (CLUTTER_ACTOR_META (priv->trough_pan_gesture), + "StScrollBar trough pan"); + + g_signal_connect (priv->trough_pan_gesture, "recognize", + G_CALLBACK (trough_pan_recognize_cb), self); + g_signal_connect (priv->trough_pan_gesture, "end", + G_CALLBACK (trough_pan_end_cb), self); + g_signal_connect (priv->trough_pan_gesture, "cancel", + G_CALLBACK (trough_pan_cancel_cb), self); + + clutter_actor_add_action (CLUTTER_ACTOR (priv->trough), CLUTTER_ACTION (priv->trough_pan_gesture)); priv->handle = (ClutterActor *) g_object_new (ST_TYPE_WIDGET, NULL); st_widget_set_track_hover (ST_WIDGET (priv->handle), TRUE); @@ -948,12 +898,22 @@ st_scroll_bar_init (StScrollBar *self) st_widget_set_style_class_name (ST_WIDGET (priv->handle), "hhandle"); clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->handle)); - g_signal_connect (priv->handle, "button-press-event", - G_CALLBACK (handle_button_press_event_cb), self); - g_signal_connect (priv->handle, "button-release-event", - G_CALLBACK (handle_button_release_event_cb), self); - g_signal_connect (priv->handle, "motion-event", - G_CALLBACK (handle_motion_event_cb), self); + + priv->handle_pan_gesture = CLUTTER_PAN_GESTURE (clutter_pan_gesture_new ()); + clutter_pan_gesture_set_begin_threshold (priv->handle_pan_gesture, 0); + clutter_actor_meta_set_name (CLUTTER_ACTOR_META (priv->handle_pan_gesture), + "StScrollBar handle pan"); + + g_signal_connect (priv->handle_pan_gesture, "recognize", + G_CALLBACK (handle_pan_recognize_cb), self); + g_signal_connect (priv->handle_pan_gesture, "pan-update", + G_CALLBACK (handle_pan_update_cb), self); + g_signal_connect (priv->handle_pan_gesture, "end", + G_CALLBACK (handle_pan_end_cb), self); + g_signal_connect (priv->handle_pan_gesture, "cancel", + G_CALLBACK (handle_pan_cancel_cb), self); + + clutter_actor_add_action (CLUTTER_ACTOR (priv->handle), CLUTTER_ACTION (priv->handle_pan_gesture)); clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);